package concurrent;

import java.util.concurrent.CyclicBarrier;

/**
 * @Description: TODO 可重用屏障 所有的线程必须同时到达屏障位置，才能继续执行
 * @Author: wzj
 * @Date: 2020/4/11 11:23
 * 在CyclicBarrier类的内部有一个计数器，每个线程在到达屏障点的时候都会调用await方法将自己阻塞，此时计数器会减1，当计数器减为0的时候所有因调用await方法而被阻塞的线程将被唤醒。
 */
public class CyclicBarrierDemo {
    static class TaskThread extends Thread {

        CyclicBarrier barrier;

        public TaskThread(CyclicBarrier barrier) {
            this.barrier = barrier;
        }

        @Override
        public void run() {
            try {
                System.out.println(getName() + " 到达栅栏 A");
                barrier.await();//第一次使用 所有线程都到这里，才能执行下一步
                Thread.sleep(1000);
                System.out.println(getName() + " 冲破栅栏 A");
                Thread.sleep(2000);
                System.out.println(getName() + " 到达栅栏 B");
                barrier.await();//可以多次利用 所有线程都到这里，才能执行下一步
                Thread.sleep(1000);
                System.out.println(getName() + " 冲破栅栏 B");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        int threadNum = 5;
        //threadNum数量的线程都到达栅栏，则执行Runnable这个线程
        CyclicBarrier barrier = new CyclicBarrier(threadNum, new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + " 完成最后任务");
            }
        });

        for(int i = 0; i < threadNum; i++) {
            new TaskThread(barrier).start();
        }
    }
}
